﻿using System;
using System.Windows.Forms;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.AudioVideoPlayback;

namespace Project
{
  class Graphics
  {
    public Graphics(Control control)
    {
      control.KeyPress += new KeyPressEventHandler(control_KeyPress);

      PresentParameters presentParameters = new PresentParameters();
      presentParameters.Windowed = true;
      presentParameters.SwapEffect = SwapEffect.Copy;


      this.device = new Device(Manager.Adapters.Default.Adapter, DeviceType.Hardware, control, CreateFlags.SoftwareVertexProcessing, presentParameters);
      this.device.VertexFormat = CustomVertex.PositionTextured.Format;
      this.device.RenderState.Lighting = false;

      this.device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, -1.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
      this.device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, (float)this.device.Viewport.Width / (float)this.device.Viewport.Height, 1.0f, 200.0f);

      //ImageInformation imageInformation = TextureLoader.ImageInformationFromFile("../../Image.jpg");
      int w = 800; 
      int h = 600;
      this.vertices = Quad(1, (float)h / (float)w);

      this.effectNone = Effect.FromFile(this.device, "../../Filter/None.fx", null, ShaderFlags.None, null);
      this.invertFilterEffect = Effect.FromFile(this.device, "../../Filter/InvertShader.fx", null, ShaderFlags.None, null);
      this.noiseEffect = Effect.FromFile(this.device, "../../Filter/AddNoise.fx", null, ShaderFlags.None, null);
      this.sobelEdgeEffect = Effect.FromFile(this.device, "../../Filter/SobelEdgeFilter.fx", null, ShaderFlags.None, null);
      this.euclidianColorEffect = Effect.FromFile(this.device, "../../Filter/EuclidianColorFilter.fx", null, ShaderFlags.None, null);
      this.hueModifierEffect = Effect.FromFile(this.device, "../../Filter/HUEModifier.fx", null, ShaderFlags.None, null);
      this.sepiaEffect = Effect.FromFile(this.device, "../../Filter/Sepia.fx", null, ShaderFlags.None, null);

      this.effect = this.effectNone;
      this.fvalue1 = 0;



      this.video = new Video("02a.wmv");
      //this.video = new Video("a.avi");
      this.video.TextureReadyToRender += new TextureRenderEventHandler(Video_TextureReadyToRender);
      this.video.Ending += new EventHandler(video_Ending);
      this.video.Stopping += new EventHandler(video_Stopping);
      this.video.RenderToTexture(this.device);
      this.video.Play();

    }

    void video_Stopping(object sender, EventArgs e)
    {
      throw new NotImplementedException();
    }

    void video_Ending(object sender, EventArgs e)
    {
      this.video.CurrentPosition = 0;
      this.video.Play();
    }

    public void Render()
    {
      this.device.Clear(ClearFlags.Target, 0, 0, 0);
      this.device.BeginScene();

      this.device.Transform.World = Matrix.Translation(-0.5f, -0.5f, 1);
      this.device.Transform.World *= Matrix.Scaling(2, 2, 2);
      this.device.Transform.World *= Matrix.RotationZ(0.2f);
      //this.device.Transform.World *= Matrix.RotationX(0.2f);

      this.effect.SetValue("imageTexture", this.texture);
      if (this.effect == this.noiseEffect || this.effect == this.hueModifierEffect || this.effect == this.sepiaEffect)
      {
        this.effect.SetValue("fvalue1", this.fvalue1);
      }
      if (this.effect == this.sepiaEffect)
      {
        this.effect.SetValue("fvalue2", this.fvalue2);
      }
      if (this.effect == this.sobelEdgeEffect)
      {
        this.effect.SetValue("width", 300);
        this.effect.SetValue("height", 300);
      }

      this.effect.Begin(0);
      this.effect.BeginPass(0);
      this.device.DrawUserPrimitives(PrimitiveType.TriangleStrip, 2, this.vertices);
      this.effect.EndPass();
      this.effect.End();

      this.device.EndScene();
      this.device.Present();
    }

    private Device device;

    private CustomVertex.PositionTextured[] vertices;
    private Texture texture;
    private Effect effect;

    private Effect effectNone;
    private Effect invertFilterEffect;
    private Effect noiseEffect;
    private Effect sobelEdgeEffect;
    private Effect euclidianColorEffect;
    private Effect hueModifierEffect;
    private Effect sepiaEffect;

    private Video video;
    private float fvalue1;
    private float fvalue2;

    private void control_KeyPress(object sender, KeyPressEventArgs e)
    {
      if (e.KeyChar == '0') this.effect = this.effectNone;
      if (e.KeyChar == 'i') this.effect = this.invertFilterEffect;
      if (e.KeyChar == 'n') this.effect = this.noiseEffect;
      if (e.KeyChar == 's') this.effect = this.sobelEdgeEffect;
      if (e.KeyChar == 'e') this.effect = this.euclidianColorEffect;
      if (e.KeyChar == 'h') this.effect = this.hueModifierEffect;
      if (e.KeyChar == 'p') this.effect = this.sepiaEffect;

      if (e.KeyChar == '+') this.fvalue1 += 0.05f;
      if (e.KeyChar == '#') this.fvalue1 -= 0.05f;
      if (e.KeyChar == 'ü') this.fvalue2 += 0.05f;
      if (e.KeyChar == 'ä') this.fvalue2 -= 0.05f;
    }

    private void Video_TextureReadyToRender(object sender, TextureRenderEventArgs e)
    {
      this.texture = e.Texture;
      Render();
    }

    private CustomVertex.PositionTextured[] Quad(float width, float height)
    {
      CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[4];
      vertices[0] = new CustomVertex.PositionTextured(0, 0, 0, 0, 1);
      vertices[1] = new CustomVertex.PositionTextured(0, height, 0, 0, 0);
      vertices[2] = new CustomVertex.PositionTextured(width, 0, 0, 1, 1);
      vertices[3] = new CustomVertex.PositionTextured(width, height, 0, 1, 0);
      return vertices;
    }
  }
}